package org.ms.springboot.elasticsearch;

import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.junit.Test;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * API操作
 *
 * @author lry
 */
public class ElasticsearchAPI extends ElasticsearchBase {

    /**
     * 返回指定字段
     */
    @Test
    public void getIncludesAPI() throws Exception {
        GetRequest request = new GetRequest("posts", "doc", "1");
        String[] includes = new String[]{"message", "*Date"};
        request.fetchSourceContext(new FetchSourceContext(true, includes, Strings.EMPTY_ARRAY));

        this.getAPIAndPrint(request);
    }

    /**
     * 返回排除指定字段
     */
    @Test
    public void getExcludesAPI() throws Exception {
        GetRequest request = new GetRequest("posts", "doc", "1");
        String[] excludes = new String[]{"message"};
        request.fetchSourceContext(new FetchSourceContext(true, Strings.EMPTY_ARRAY, excludes));

        this.getAPIAndPrint(request);
    }

    @Test
    public void getStoredFieldsAPI() throws Exception {
        GetRequest request = new GetRequest("posts", "doc", "1");
        request.storedFields("message");
        GetResponse getResponse = client.get(request);
        System.out.println(getResponse.getFields());
        String message = getResponse.getField("message").getValue();
        System.out.println(message);
    }

    private void getAPIAndPrint(GetRequest request) {
        try {
            GetResponse response = client.get(request);
            System.out.println("GetResponse: " + response.toString());
        } catch (ElasticsearchException e) {
            if (e.status() == RestStatus.NOT_FOUND) {
                System.out.println("没有找到索引");
            } else {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void delete() throws Exception {
        DeleteRequest request = new DeleteRequest("posts", "doc", "1").version(1);
        try {
            DeleteResponse deleteResponse = client.delete(request);
            System.out.println("DeleteResponse: " + deleteResponse);
            if (DocWriteResponse.Result.DELETED == deleteResponse.getResult()) {
                System.out.println("删除成功");
            } else {
                System.out.println("删除失败：" + deleteResponse.getResult());
            }
        } catch (ElasticsearchException exception) {
            if (exception.status() == RestStatus.CONFLICT) {
                System.out.println("版本冲突");
            }
        }
    }

    @Test
    public void update() throws Exception {
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("updated", new Date());
        jsonMap.put("reason", "daily update");
        UpdateRequest request = new UpdateRequest("posts", "doc", "1").doc(jsonMap);
        try {
            UpdateResponse updateResponse = client.update(request);
            System.out.println("UpdateResponse: " + updateResponse);
            if (DocWriteResponse.Result.UPDATED == updateResponse.getResult()) {
                System.out.println("更新成功");
            } else {
                System.out.println("更新失败：" + updateResponse.getResult());
            }
        } catch (ElasticsearchException e) {
            if (e.status() == RestStatus.CONFLICT) {
                System.out.println("版本冲突");
            }
        }
    }

    /**
     * 批量操作（execute multiple index, update and/or delete operations）
     *
     * @throws Exception
     */
    @Test
    public void bulk() throws Exception {
        BulkRequest request = new BulkRequest();
        request.add(new DeleteRequest("posts", "doc", "3"));
        request.add(new UpdateRequest("posts", "doc", "2").doc(XContentType.JSON, "other", "test"));
        request.add(new IndexRequest("posts", "doc", "4").source(XContentType.JSON, "field", "baz"));

        BulkResponse bulkResponse = client.bulk(request);
        for (BulkItemResponse bulkItemResponse : bulkResponse) {
            if (bulkItemResponse.isFailed()) {
                System.out.println(bulkItemResponse.getId() + "->执行失败");
            } else {
                System.out.println(bulkItemResponse.getId() + "->执行成功");
            }
        }
    }

    @Test
    public void search() throws Exception {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy"));
        sourceBuilder.from(0);
        sourceBuilder.size(5);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        SearchRequest searchRequest = new SearchRequest();
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest);
        System.out.println("SearchResponse: " + searchResponse);
    }

}
